package com.tbynet.jwp.repository.impl;

import com.jfinal.log.Log;
import com.jfinal.plugin.ehcache.CacheKit;
import com.tbynet.jwp.framework.aop.Aop;
import com.tbynet.jwp.model.Posts;
import com.tbynet.jwp.repository.spi.PostCacheService;

import java.util.List;

/**
 * 文章缓存服务提供者
 * 基于Ehcache实现文章相关的缓存操作
 *
 * @ClassName: PostCacheServiceProvider
 * @Description: 文章缓存服务提供者，负责文章详情、列表、搜索结果的缓存管理
 * @Author: 佰亿互联
 * @Date: 2025年11月4日
 *
 * @Copyright: 2025 www.tbynet.com Inc. All rights reserved.
 * 注意: 本内容仅限于内部传阅，禁止外泄以及用于其他的商业目
 */
@Aop(PostCacheService.class)
public class PostCacheServiceImpl implements PostCacheService {

    /** 日志记录器 */
    protected final Log log = Log.getLog(PostCacheServiceImpl.class);

    // ============ 缓存名称常量 ============

    /** 文章详情缓存名称 */
    private static final String POST_CACHE = "postCache";

    /** 文章列表缓存名称 */
    private static final String POST_LIST_CACHE = "postListCache";

    /** 文章统计缓存名称 */
    private static final String POST_STATS_CACHE = "postStatsCache";

    /** 文章计数缓存名称 */
    private static final String POST_COUNT_CACHE = "postCountCache";

    // ============ 缓存键前缀常量 ============

    /** 搜索缓存键前缀 */
    private static final String SEARCH_CACHE_PREFIX = "post_search_";

    /** 高级搜索缓存键前缀 */
    private static final String ADVANCED_SEARCH_CACHE_PREFIX = "post_advanced_search_";

    // ============ 缓存过期时间常量 ============

    /** 文章详情缓存过期时间（分钟） */
    private static final int POST_CACHE_EXPIRE = 30;

    /** 文章列表缓存过期时间（分钟） */
    private static final int LIST_CACHE_EXPIRE = 10;

    /** 文章统计缓存过期时间（分钟） */
    private static final int STATS_CACHE_EXPIRE = 60;

    /** 文章计数缓存过期时间（分钟） */
    private static final int COUNT_CACHE_EXPIRE = 5;

    // ============ 文章详情缓存方法实现 ============

    @Override
    public Posts getPostFromCache(Object postId) {
        if (postId == null) {
            return null;
        }
        String cacheKey = "post_" + postId;
        try {
            Posts cachedPost = CacheKit.get(POST_CACHE, cacheKey);
            if (cachedPost != null) {
                log.debug("从缓存获取文章详情成功，文章ID：%s", postId);
            }
            return cachedPost;
        } catch (Exception e) {
            log.warn("从缓存获取文章详情失败，文章ID：%s", postId, e);
            return null;
        }
    }

    @Override
    public void putPostToCache(Posts post) {
        if (post == null || post.getID() == null) {
            return;
        }

        String cacheKey = "post_" + post.getID();
        try {
            CacheKit.put(POST_CACHE, cacheKey, post);
            log.debug("文章详情缓存成功，文章ID：%s", post.getID());
        } catch (Exception e) {
            log.warn("文章详情缓存失败，文章ID：%s", post.getID(), e);
        }
    }

    @Override
    public void removePostFromCache(Object postId) {
        if (postId == null) {
            return;
        }

        String cacheKey = "post_" + postId;
        try {
            CacheKit.remove(POST_CACHE, cacheKey);
            log.debug("移除文章详情缓存成功，文章ID：%s", postId);
        } catch (Exception e) {
            log.warn("移除文章详情缓存失败，文章ID：%s", postId, e);
        }
    }

    // ============ 文章列表缓存方法实现 ============

    @Override
    public List<Posts> getPostListFromCache(String cacheKey) {
        if (cacheKey == null) {
            return null;
        }
        try {
            return CacheKit.get(POST_LIST_CACHE, cacheKey);
        } catch (Exception e) {
            log.warn("从缓存获取文章列表失败，缓存键：%s", cacheKey, e);
            return null;
        }
    }

    @Override
    public void putPostListToCache(String cacheKey, List<Posts> posts) {
        if (cacheKey == null || posts == null) {
            return;
        }

        try {
            CacheKit.put(POST_LIST_CACHE, cacheKey, posts);
            log.debug("文章列表缓存成功，缓存键：%s，文章数量：%s", cacheKey, posts.size());
        } catch (Exception e) {
            log.warn("文章列表缓存失败，缓存键：%s", cacheKey, e);
        }
    }

    // ============ 文章计数缓存方法实现 ============

    @Override
    public Long getPostCountFromCache(String countCacheKey) {
        if (countCacheKey == null) {
            return null;
        }

        try {
            Object cached = CacheKit.get(POST_COUNT_CACHE, countCacheKey);
            if (cached instanceof Long) {
                return (Long) cached;
            } else if (cached instanceof Integer) {
                return ((Integer) cached).longValue();
            }
            return null;
        } catch (Exception e) {
            log.warn("从缓存获取文章总数失败，缓存键：%s", countCacheKey, e);
            return null;
        }
    }

    @Override
    public void putPostCountToCache(String countCacheKey, long totalRow) {
        if (countCacheKey == null) {
            return;
        }

        try {
            CacheKit.put(POST_COUNT_CACHE, countCacheKey, totalRow);
            log.debug("文章总数缓存成功，缓存键：%s，总数：%s", countCacheKey, totalRow);
        } catch (Exception e) {
            log.warn("文章总数缓存失败，缓存键：%s", countCacheKey, e);
        }
    }

    @Override
    public void removePostCountFromCache(String countCacheKey) {
        if (countCacheKey == null) {
            return;
        }

        try {
            CacheKit.remove(POST_COUNT_CACHE, countCacheKey);
            log.debug("移除文章计数缓存成功，缓存键：%s", countCacheKey);
        } catch (Exception e) {
            log.warn("移除文章计数缓存失败，缓存键：%s", countCacheKey, e);
        }
    }

    // ============ 文章统计缓存方法实现 ============

    @Override
    public Object getPostStatsFromCache(String statsKey) {
        if (statsKey == null) {
            return null;
        }

        try {
            return CacheKit.get(POST_STATS_CACHE, statsKey);
        } catch (Exception e) {
            log.warn("从缓存获取文章统计失败，缓存键：%s", statsKey, e);
            return null;
        }
    }

    @Override
    public void putPostStatsToCache(String statsKey, Object stats) {
        if (statsKey == null || stats == null) {
            return;
        }

        try {
            CacheKit.put(POST_STATS_CACHE, statsKey, stats);
            log.debug("文章统计缓存成功，缓存键：%s", statsKey);
        } catch (Exception e) {
            log.warn("文章统计缓存失败，缓存键：%s", statsKey, e);
        }
    }

    // ============ 缓存键生成方法实现 ============

    @Override
    public String generateListCacheKey(String type, String status, String category, String tag, int page, int size) {
        StringBuilder key = new StringBuilder("post_list_");
        key.append(type != null ? type : "post").append("_").append(status != null ? status : "all");

        if (category != null && !category.trim().isEmpty()) {
            key.append("_cat_").append(category.trim().hashCode());
        }
        if (tag != null && !tag.trim().isEmpty()) {
            key.append("_tag_").append(tag.trim().hashCode());
        }
        key.append("_page_").append(page).append("_size_").append(size);

        return key.toString();
    }

    @Override
    public String generateCountCacheKey(String type, String status, String category, String tag, String keyword) {
        StringBuilder key = new StringBuilder("post_count_");
        key.append(type != null ? type : "post").append("_").append(status != null ? status : "all");

        if (category != null && !category.trim().isEmpty()) {
            key.append("_cat_").append(category.trim().hashCode());
        }
        if (tag != null && !tag.trim().isEmpty()) {
            key.append("_tag_").append(tag.trim().hashCode());
        }
        if (keyword != null && !keyword.trim().isEmpty()) {
            key.append("_kw_").append(keyword.trim().hashCode());
        }

        return key.toString();
    }

    @Override
    public String generateStatsCacheKey(String type) {
        return "post_stats_" + (type != null ? type : "post");
    }

    // ============ 搜索缓存方法实现 ============

    @Override
    public String generateSearchListCacheKey(String type, String status, String keyword,
                                             String category, String tag, int page, int size) {
        StringBuilder key = new StringBuilder(SEARCH_CACHE_PREFIX + "list_");
        key.append(type != null ? type : "post").append("_").append(status != null ? status : "all");

        if (keyword != null && !keyword.trim().isEmpty()) {
            key.append("_keyword_").append(keyword.trim().hashCode());
        }

        if (category != null && !category.trim().isEmpty()) {
            key.append("_cat_").append(category.trim().hashCode());
        }
        if (tag != null && !tag.trim().isEmpty()) {
            key.append("_tag_").append(tag.trim().hashCode());
        }
        key.append("_page_").append(page).append("_size_").append(size);

        return key.toString();
    }

    @Override
    public String generateSearchCountCacheKey(String type, String status, String keyword,
                                              String category, String tag) {
        StringBuilder key = new StringBuilder(SEARCH_CACHE_PREFIX + "count_");
        key.append(type != null ? type : "post").append("_").append(status != null ? status : "all");

        if (keyword != null && !keyword.trim().isEmpty()) {
            key.append("_keyword_").append(keyword.trim().hashCode());
        }

        if (category != null && !category.trim().isEmpty()) {
            key.append("_cat_").append(category.trim().hashCode());
        }
        if (tag != null && !tag.trim().isEmpty()) {
            key.append("_tag_").append(tag.trim().hashCode());
        }

        return key.toString();
    }

    @Override
    public String generateAdvancedSearchListCacheKey(String type, String status, String keyword,
                                                     String category, String tag, String month,
                                                     Boolean sticky, int page, int size) {
        StringBuilder key = new StringBuilder(ADVANCED_SEARCH_CACHE_PREFIX + "list_");
        key.append(type != null ? type : "post").append("_").append(status != null ? status : "all");

        // 添加搜索关键词
        if (keyword != null && !keyword.trim().isEmpty()) {
            key.append("_keyword_").append(keyword.trim().hashCode());
        }

        // 添加分类
        if (category != null && !category.trim().isEmpty()) {
            key.append("_cat_").append(category.trim().hashCode());
        }

        // 添加标签
        if (tag != null && !tag.trim().isEmpty()) {
            key.append("_tag_").append(tag.trim().hashCode());
        }

        // 添加月份
        if (month != null && !month.trim().isEmpty()) {
            key.append("_month_").append(month.trim().hashCode());
        }

        // 添加置顶状态
        if (sticky != null) {
            key.append("_sticky_").append(sticky ? 1 : 0);
        }

        key.append("_page_").append(page).append("_size_").append(size);

        return key.toString();
    }

    @Override
    public String generateAdvancedSearchCountCacheKey(String type, String status, String keyword,
                                                      String category, String tag, String month,
                                                      Boolean sticky) {
        StringBuilder key = new StringBuilder(ADVANCED_SEARCH_CACHE_PREFIX + "count_");
        key.append(type != null ? type : "post").append("_").append(status != null ? status : "all");

        // 添加搜索关键词
        if (keyword != null && !keyword.trim().isEmpty()) {
            key.append("_keyword_").append(keyword.trim().hashCode());
        }

        // 添加分类
        if (category != null && !category.trim().isEmpty()) {
            key.append("_cat_").append(category.trim().hashCode());
        }

        // 添加标签
        if (tag != null && !tag.trim().isEmpty()) {
            key.append("_tag_").append(tag.trim().hashCode());
        }

        // 添加月份
        if (month != null && !month.trim().isEmpty()) {
            key.append("_month_").append(month.trim().hashCode());
        }

        // 添加置顶状态
        if (sticky != null) {
            key.append("_sticky_").append(sticky ? 1 : 0);
        }

        return key.toString();
    }

    // ============ 缓存清除方法实现 ============

    @Override
    public void clearAllPostCache() {
        try {
            CacheKit.removeAll(POST_CACHE);
            CacheKit.removeAll(POST_LIST_CACHE);
            CacheKit.removeAll(POST_STATS_CACHE);
            CacheKit.removeAll(POST_COUNT_CACHE);
            log.info("清除所有文章缓存成功");
        } catch (Exception e) {
            log.warn("清除所有文章缓存失败", e);
        }
    }

    @Override
    public void clearSearchCache(String keyword) {
        if (keyword == null || keyword.trim().isEmpty()) {
            return;
        }

        try {
            String keywordHash = String.valueOf(keyword.trim().hashCode());
            clearCacheByPattern(SEARCH_CACHE_PREFIX + "*keyword_" + keywordHash + "*");
            log.info("清除搜索缓存成功，关键词：%s", keyword);
        } catch (Exception e) {
            log.warn("清除搜索缓存失败，关键词：%s", keyword, e);
        }
    }

    @Override
    public void clearAdvancedSearchCache() {
        try {
            clearCacheByPattern(ADVANCED_SEARCH_CACHE_PREFIX + "*");
            log.info("清除高级搜索缓存成功");
        } catch (Exception e) {
            log.warn("清除高级搜索缓存失败", e);
            // 降级方案：直接清除整个缓存区域
            CacheKit.removeAll(POST_LIST_CACHE);
            CacheKit.removeAll(POST_COUNT_CACHE);
        }
    }

    // ============ 批量缓存操作方法实现 ============

    @Override
    public List<Posts> batchGetPostsFromCache(List<Object> postIds) {
        List<Posts> result = new java.util.ArrayList<>();
        if (postIds == null || postIds.isEmpty()) {
            return result;
        }

        for (Object postId : postIds) {
            Posts post = getPostFromCache(postId);
            if (post != null) {
                result.add(post);
            }
        }
        return result;
    }

    @Override
    public void batchPutPostsToCache(List<Posts> posts) {
        if (posts == null || posts.isEmpty()) {
            return;
        }

        for (Posts post : posts) {
            putPostToCache(post);
        }
        log.debug("批量缓存文章成功，文章数量：%s", posts.size());
    }

    @Override
    public void batchRemovePostsFromCache(List<Object> postIds) {
        if (postIds == null || postIds.isEmpty()) {
            return;
        }

        for (Object postId : postIds) {
            removePostFromCache(postId);
        }
        log.debug("批量移除文章缓存成功，文章数量：%s", postIds.size());
    }

    // ============ 私有方法 ============

    /**
     * 按模式清除缓存
     *
     * @param pattern 模式字符串
     */
    private void clearCacheByPattern(String pattern) {
        try {
            net.sf.ehcache.Cache listCache = CacheKit.getCacheManager().getCache(POST_LIST_CACHE);
            net.sf.ehcache.Cache countCache = CacheKit.getCacheManager().getCache(POST_COUNT_CACHE);

            int removedListKeys = 0;
            int removedCountKeys = 0;

            // 清除列表缓存中匹配模式的键
            List<Object> listKeys = listCache.getKeys();
            for (Object key : listKeys) {
                if (key.toString().contains(pattern)) {
                    listCache.remove(key);
                    removedListKeys++;
                }
            }

            // 清除计数缓存中匹配模式的键
            List<Object> countKeys = countCache.getKeys();
            for (Object key : countKeys) {
                if (key.toString().contains(pattern)) {
                    countCache.remove(key);
                    removedCountKeys++;
                }
            }

            log.debug("按模式清除缓存完成，pattern: %s，移除列表键: %s个，计数键: %s个",
                    pattern, removedListKeys, removedCountKeys);

        } catch (Exception e) {
            log.warn("按模式清除缓存失败，pattern: %s", pattern, e);
        }
    }

    /**
     * 清除所有搜索相关的缓存（简化版本）
     */
    public void clearAllSearchCache() {
        try {
            clearCacheByPattern(SEARCH_CACHE_PREFIX + "*");
            log.info("清除所有搜索缓存成功");
        } catch (Exception e) {
            log.warn("清除所有搜索缓存失败", e);
            // 降级方案：直接清除整个缓存区域
            CacheKit.removeAll(POST_LIST_CACHE);
            CacheKit.removeAll(POST_COUNT_CACHE);
        }
    }
}